package org.cqut.system.common.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.file.FileNameUtil;
import cn.hutool.core.lang.UUID;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.lkx.util.ExcelUtil;
import org.apache.commons.io.IOUtils;
import org.cqut.framework.utils.EncryptionUtils;
import org.cqut.framework.utils.FileUtils;
import org.cqut.system.common.dto.WorkDto;
import org.cqut.system.common.service.CommonService;
import org.cqut.system.resource.domain.Resource;
import org.cqut.system.resource.service.ResourceService;
import org.cqut.system.user.dto.UserExcelDTO;
import org.cqut.system.user.service.SysUserService;
import org.cqut.system.work_content.service.WorkContentService;
import org.cqut.system.work_record.service.WorkRecordService;
import org.cqut.system.work_submit.domain.WorkSubmit;
import org.cqut.system.work_submit.service.WorkSubmitService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author XiAoXu
 * @date 2021/11/3 22:57
 * @description
 */
@Service
public class CommonServiceImpl implements CommonService {

    @Autowired
    private SysUserService userService;

    @Autowired
    private ResourceService resourceService;

    @Autowired
    private WorkContentService workContentService;

    @Autowired
    private WorkRecordService workRecordService;

    @Autowired
    private WorkSubmitService workSubmitService;

    @Autowired
    private JavaMailSender mailSender;

    @Value("${spring.mail.username}")
    private String from;

    @Override
    public String sendEmail(String email) {
        try {
            //创建一个MINE消息
            MimeMessage message = mailSender.createMimeMessage();
            MimeMessageHelper mineHelper = new MimeMessageHelper(message, true);
            //谁发
            mineHelper.setFrom(from);
            //谁要接收
            mineHelper.setTo(email);
            //邮件主题
            mineHelper.setSubject("用户校验");
            //邮件内容   true 表示带有附件或html
            //5.邮件内容
            //5.1获取随机字符串
            String charAndNumbers = EncryptionUtils.getCharAndNumbers();
            //5.2拼HTML模板
            String content = "<html><body><h1>您的验证码为:</h1><h3>" + charAndNumbers + "</h3></body></html>";
            mineHelper.setText(content, true);
            //6.发送邮件
            mailSender.send(message);
            return charAndNumbers;
        } catch (MessagingException e) {
            return "";
        }
    }

    @Override
    public String uploadAvatar(MultipartFile file, String username) {
        String path = "";
        try {
            path = FileUtils.saveImg(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return userService.updateAvatar(path, username) ? path : "";
    }

    @Override
    public boolean uploadResource(MultipartFile[] multipartFiles) {
        Resource resource = new Resource();
        List<Resource> resources = new ArrayList<>();
        for (MultipartFile multipartFile : multipartFiles) {
            //1.获取File名称
            String fileName = multipartFile.getOriginalFilename();
            //2.获取File种类
            String type = FileNameUtil.getSuffix(fileName);
            //3.获取File大小
            long size = multipartFile.getSize();
            //4.上传文件
            String path = FileUtils.saveResource(multipartFile);
            //5.创建对象
            resource.setResourceName(fileName);
            resource.setResourceType(type);
            resource.setResourceSize(size);
            resource.setResourceUrl(path);
            resources.add(resource);
        }
        return resourceService.saveBatch(resources);
    }

    @Override
    public boolean uploadWork(MultipartFile file, WorkDto workDto) {
        String path = "";
        try {
            path = FileUtils.saveWork(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return workContentService.saveWork(path, workDto);
    }

    @Override
    public boolean submitWork(MultipartFile file, String recordId) {
        String path = "";
        try {
            path = FileUtils.saveSubmit(file);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return workSubmitService.saveSubmit(path, recordId);
    }

    @Override
    public void downloadWork(HttpServletResponse response, String recordId) {
        String workPath = workRecordService.getWorkPath(recordId);
        String filePath = "C:/Users/XiAoXu/Desktop/upload" + workPath;
        OutputStream os = null;
        InputStream is = null;
        try {
            // 取得输出流
            os = response.getOutputStream();
            // 清空输出流
            response.reset();
            response.setContentType("application/x-download;charset=utf-8");
            //Content-Disposition中指定的类型是文件的扩展名，并且弹出的下载对话框中的文件类型图片是按照文件的扩展名显示的，点保存后，文件以filename的值命名，
            // 保存类型以Content中设置的为准。注意：在设置Content-Disposition头字段之前，一定要设置Content-Type头字段。
            //把文件名按UTF-8取出，并按ISO8859-1编码，保证弹出窗口中的文件名中文不乱码，中文不要太多，最多支持17个中文，因为header有150个字节限制。
            response.setHeader("Content-Disposition", "attachment;filename=" + new String(("作业.txt").getBytes("utf-8"), "ISO8859-1"));
            //读取流
            File f = new File(filePath);
            is = new FileInputStream(f);
            //复制
            IOUtils.copy(is, response.getOutputStream());
            response.getOutputStream().flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //文件的关闭放在finally中
        finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void download(HttpServletResponse response, String resourceId) {
        Resource resource = resourceService.getById(resourceId);
        String filePath = "C:/Users/XiAoXu/Desktop/upload" + resource.getResourceUrl();
        OutputStream os = null;
        InputStream is = null;
        try {
            // 取得输出流
            os = response.getOutputStream();
            // 清空输出流
            response.reset();
            response.setContentType("application/x-download;charset=utf-8");
            //Content-Disposition中指定的类型是文件的扩展名，并且弹出的下载对话框中的文件类型图片是按照文件的扩展名显示的，点保存后，文件以filename的值命名，
            // 保存类型以Content中设置的为准。注意：在设置Content-Disposition头字段之前，一定要设置Content-Type头字段。
            //把文件名按UTF-8取出，并按ISO8859-1编码，保证弹出窗口中的文件名中文不乱码，中文不要太多，最多支持17个中文，因为header有150个字节限制。
            response.setHeader("Content-Disposition", "attachment;filename=" + new String((resource.getResourceName() + "." + resource.getResourceType()).getBytes("utf-8"), "ISO8859-1"));
            //读取流
            File f = new File(filePath);
            is = new FileInputStream(f);
            //复制
            IOUtils.copy(is, response.getOutputStream());
            response.getOutputStream().flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //文件的关闭放在finally中
        finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void downloadSubmit(HttpServletResponse response, String submitId) {
        WorkSubmit submit = workSubmitService.getById(submitId);
        String filePath = "C:/Users/XiAoXu/Desktop/upload" + submit.getSubmitPath();
        OutputStream os = null;
        InputStream is = null;
        try {
            // 取得输出流
            os = response.getOutputStream();
            // 清空输出流
            response.reset();
            response.setContentType("application/x-download;charset=utf-8");
            //Content-Disposition中指定的类型是文件的扩展名，并且弹出的下载对话框中的文件类型图片是按照文件的扩展名显示的，点保存后，文件以filename的值命名，
            // 保存类型以Content中设置的为准。注意：在设置Content-Disposition头字段之前，一定要设置Content-Type头字段。
            //把文件名按UTF-8取出，并按ISO8859-1编码，保证弹出窗口中的文件名中文不乱码，中文不要太多，最多支持17个中文，因为header有150个字节限制。
            response.setHeader("Content-Disposition", "attachment;filename=" + new String(("提交的作业.txt").getBytes("utf-8"), "ISO8859-1"));
            //读取流
            File f = new File(filePath);
            is = new FileInputStream(f);
            //复制
            IOUtils.copy(is, response.getOutputStream());
            response.getOutputStream().flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //文件的关闭放在finally中
        finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public String pack(HttpServletResponse response, List<String> ids) throws IOException {
        String zipPath = "C:\\Users\\XiAoXu\\Desktop\\upload\\score/" + UUID.fastUUID() + ".zip";
        QueryWrapper<WorkSubmit> wrapper = new QueryWrapper<>();
        wrapper.select("submit_path");
        wrapper.in("record_id", ids);
        List<File> paths = workSubmitService
                .list(wrapper)
                .stream()
                .map(item -> new File("C:/Users/XiAoXu/Desktop/upload" + item.getSubmitPath()))
                .collect(Collectors.toList());
        File zipFile = new File(zipPath);
        FileUtil.touch(zipFile);
        FileUtils.toZip(paths,zipFile);
        return zipPath;
    }

    @Override
    public void downloadSubmits(HttpServletResponse response, String path) {
        OutputStream os = null;
        InputStream is = null;
        try {
            // 取得输出流
            os = response.getOutputStream();
            // 清空输出流
            response.reset();
            response.setContentType("application/x-download;charset=utf-8");
            //Content-Disposition中指定的类型是文件的扩展名，并且弹出的下载对话框中的文件类型图片是按照文件的扩展名显示的，点保存后，文件以filename的值命名，
            // 保存类型以Content中设置的为准。注意：在设置Content-Disposition头字段之前，一定要设置Content-Type头字段。
            //把文件名按UTF-8取出，并按ISO8859-1编码，保证弹出窗口中的文件名中文不乱码，中文不要太多，最多支持17个中文，因为header有150个字节限制。
            response.setHeader("Content-Disposition", "attachment;filename=" + new String(("作业.zip").getBytes("utf-8"), "ISO8859-1"));
            //读取流
            File f = new File(path);
            is = new FileInputStream(f);
            //复制
            IOUtils.copy(is, response.getOutputStream());
            response.getOutputStream().flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
        //文件的关闭放在finally中
        finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (os != null) {
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void template(HttpServletResponse response) throws Exception {
        List<UserExcelDTO> list = new ArrayList<>();
        for (int i = 0; i < 3; i++) {
            UserExcelDTO userExcelDTO = new UserExcelDTO();
            userExcelDTO.setUsername("1815010138" + i);
            userExcelDTO.setEmail("805505617" + i + "@qq.com");
            userExcelDTO.setClassName("软件技术1801" + i);
            list.add(userExcelDTO);
        }
        ExcelUtil.exportExcelOutputStream(response, list, UserExcelDTO.class, "学生导入模板");
    }
}
